package entutils

import (
	"entgo.io/ent/entc"
	"entgo.io/ent/entc/gen"
	"log"
	"strings"
	"text/template"
)

type Option = entc.Option

type GenerateConfig struct {
	features          []gen.Feature
	err               error
	templates         []*gen.Template
	schemaDir         string
	options           []Option
	externalTemplates []*Template
	baseDir           string
}

func NewGenerateConfig(schemaDir string, options ...Option) *GenerateConfig {
	baseDir, err := findGoModRoot(schemaDir)
	return &GenerateConfig{
		schemaDir: schemaDir,
		options:   options,
		baseDir:   baseDir,
		err:       err,
	}
}
func (cfg *GenerateConfig) genConfig() *gen.Config {
	return &gen.Config{
		Features:  cfg.features,
		Templates: cfg.templates,
		Hooks: []gen.Hook{
			func(generator gen.Generator) gen.Generator {
				return gen.GenerateFunc(func(g *gen.Graph) error {
					log.Println("---数据库模板---")
					err := generator.Generate(g)
					if err != nil {
						log.Println("\t error: ", err.Error())
						return err
					}
					log.Println("\t success ")
					log.Println("---数据库模板--- \n")
					types := g.Nodes

					log.Println("---外部模板---")
					if len(cfg.externalTemplates) > 0 {
						for _, t := range cfg.externalTemplates {
							for _, typ := range types {
								err = t.Execute(cfg.baseDir, typ)
								if err != nil {
									log.Println("\t error ->", t.template.Name(), err.Error())
									return err
								} else {
									log.Println("\t success ->", t.out)
								}
							}
						}
					}
					log.Println("---外部模板---")
					return nil
				})
			},
		},
	}
}
func (cfg *GenerateConfig) AddTemplate(pattern string) *GenerateConfig {
	var (
		temp *gen.Template
	)
	if cfg.err != nil {
		return cfg
	}
	temp, cfg.err = gen.NewTemplate(pattern).ParseGlob(pattern)
	if cfg.err != nil {
		return cfg
	}
	cfg.templates = append(cfg.templates, temp)
	return cfg
}
func (cfg *GenerateConfig) AddExternalTemplates(pattern string) *GenerateConfig {
	var (
		temp *template.Template
	)
	if cfg.err != nil {
		return cfg
	}
	temp, cfg.err = template.New(pattern).ParseGlob(pattern)
	if cfg.err != nil {
		return cfg
	}

	for _, t := range temp.Templates() {
		if strings.HasPrefix(t.Name(), "/") {
			cfg.externalTemplates = append(cfg.externalTemplates, NewTemplate(t))
		}
	}
	return cfg
}
